<template>
  <div class="u-crud">
    <div v-show="searchVisible">
      <slot name="query"></slot>
    </div>
    <div ref="toolRef" class="tool">
      <div>
        <el-button v-if="crud && crud.save" :icon="Plus" class="u-small" type="primary" @click="crud.save">
          新增
        </el-button>
        <el-button
          v-if="crud && crud.update"
          :icon="EditPen"
          class="u-small"
          :disabled="state.selections?.length != 1"
          type="success"
          @click="update(state.selections[0])"
        >
          修改
        </el-button>
        <el-popover v-if="crud && crud.remove" :visible="state.visible" placement="top" :width="160">
          <p style="margin-bottom: 10px">您确定要删除吗？</p>
          <div style="text-align: right; margin: 0">
            <el-button size="small" text @click="state.visible = false">取消</el-button>
            <el-button size="small" type="primary" @click="_remove(state.selections)">确认</el-button>
          </div>
          <template #reference>
            <el-button
              :icon="Delete"
              class="u-small"
              :loading="btnLoading"
              :disabled="state.selections?.length == 0"
              type="danger"
              @click="state.visible = true"
            >
              删除
            </el-button>
          </template>
        </el-popover>
        <slot name="tool"></slot>
      </div>
      <div>
        <el-tooltip v-if="$slots.search" :content="searchVisible ? '隐藏搜索' : '显示搜索'" placement="top">
          <el-button size="small" circle :icon="Search" @click="searchVisible = !searchVisible"></el-button>
        </el-tooltip>
        <el-tooltip content="刷新" placement="top">
          <el-button size="small" circle :icon="Refresh" @click="refresh"></el-button>
        </el-tooltip>
      </div>
    </div>
    <Table
      ref="tableRef"
      :table="table"
      :crud="crud"
      :max-height="maxHeight"
      @page="page"
      @on-selection="val => (state.selections = val)"
      @input-blur="val => $emit('inputBlur', val)"
    >
      <template v-for="v in prop" #[v]="scope">
        <slot :name="v" :row="scope.row"></slot>
      </template>
    </Table>
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
import { Plus, EditPen, Delete, Search, Refresh } from '@element-plus/icons-vue'
import { throttle } from 'undraw-ui'
import Table, { TableApi } from './table.vue'
export type { TableApi } from './table.vue'

export interface CrudApi {
  save?: () => void
  update?: (val: any) => void
  /**
   * use throttle 节流
   */
  remove?: (val: any[], finish: () => void) => void
}

interface Props {
  crud?: CrudApi
  table: TableApi
  maxHeight?: number | string
}

const props = withDefaults(defineProps<Props>(), {})

const searchVisible = ref(true)
const btnLoading = ref(false)
const state = reactive({
  visible: false,
  selections: [] as any[]
})

const tableRef = ref<InstanceType<typeof Table>>()

const prop = computed(() => props.table.columns.filter(v => v.prop).map(v => v.prop as string))

const emit = defineEmits<{
  page: [current: number, size: number, finish: () => void]
  refresh: [finish: () => void]
  inputBlur: [val: any]
}>()

const page = (current: number, size: number, finish: () => void) => {
  emit('page', current, size, finish)
  emit('refresh', finish)
}

const update = (val: any) => {
  if (props.crud?.update) {
    props.crud.update(val)
  }
}

const _remove = throttle((val: any[]) => {
  state.visible = false
  if (props.crud?.remove) {
    btnLoading.value = true
    props.crud.remove(val, () => {
      btnLoading.value = false
      refresh()
    })
  }
})

const refresh = () => {
  tableRef.value?.reload()
}

const toolRef = ref()
const tableHeight = ref()
onMounted(() => {
  tableHeight.value = toolRef.value.clientHeight
})
defineExpose({
  refresh,
  resetHeaderWidth: () => tableRef.value?.resetHeaderWidth()
})
</script>

<style lang="scss" scoped>
.u-crud {
  height: 100%;
  padding: 10px;
  background-color: #fff;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  .tool {
    margin-bottom: 8px;
    display: flex;
    justify-content: space-between;
  }
  .u-table {
    flex: 1;
  }
}
</style>
<style>
.u-small {
  height: 28px !important;
  padding: 5px 11px !important;
  font-size: 12px !important;
  border-radius: calc(var(--el-border-radius-base) - 1px) !important;
}
</style>
